﻿using System;
using System.Diagnostics;

namespace Wp7Tools.Services.Cache {
	public class LocalCache : ILocalCache {
		private object _sync = new object();
		private DataStorage _storage;

		public CachePolicy CachePolicy { get; set; }
		public int CacheSize { get; set; }
		public bool IgnoreExceptions { get; set; }
		public string Folder { get; private set; }

		public LocalCache(DataStorage storage, string folder) {
			_storage = storage;
			_storage.CreateDirectory(folder);
			Folder = folder;
			CacheSize = 60;
			CachePolicy = CachePolicy.OldestOut;
			IgnoreExceptions = true;
		}

		public void SaveToCache(string filename, byte[] content) {
			try {
				string key = AddPath(filename);
				lock (_sync) {
					_storage.Save(key, content);
					TrimCache();
				}
			}
			catch (Exception ex) {
				Debug.WriteLine("Error saving file to cache: " + ex);
				if (!IgnoreExceptions) {
					throw;
				}
			}
		}

		public byte[] GetFromCache(string filename) {
			try {
				string key = AddPath(filename);
				lock (_sync) {
					if (!_storage.Exists(key)) {
						return null;
					}
					return _storage.Load(key);
				}
			}
			catch (Exception ex) {
				Debug.WriteLine("Error loading file from cache: " + ex);
				if (!IgnoreExceptions) {
					throw;
				}
				return null;
			}
		}

		private string AddPath(string path) {
			return Folder + "\\" + path;
		}

		public virtual void TrimCache() {
			string[] files = _storage.List(Folder);
			if (files.Length <= CacheSize) return;

			try {
				string fileToDelete = "";
				switch (CachePolicy) {
					case CachePolicy.OldestOut:
						string oldest = _storage.GetOldestFile(Folder);
						fileToDelete = oldest;
						break;
					case CachePolicy.Random:
						int index = new Random(DateTime.Now.Millisecond).Next(0, files.Length);
						fileToDelete = files[index];
						break;
				}
				_storage.Delete(fileToDelete);

			}
			catch (Exception ex) {
				Debug.WriteLine("Error removing file from cache: " + ex);
				if (!IgnoreExceptions) {
					throw;
				}
			}
		}
	}

	public class FakeLocalCache : ILocalCache {
		public void SaveToCache(string filename, byte[] content) {
		}

		public byte[] GetFromCache(string filename) {
			return null;
		}
	}
}